#include "game_server.h"
#include "wrap_directinput8.h"
#include "wrap_directinputdevice8.h"
#include "wrap_directinputeffect.h"
#include "opcode.h"


int WrapperDirectInput8::GetID(){
	return this->id;
}
void WrapperDirectInput8::SetID(int id){
	this->id = id;
}

STDMETHODIMP WrapperDirectInput8::QueryInterface(THIS_ REFIID riid, void ** ppvObj){
	Log::log("WrapperDirectInput8::QueryInterface() called\n");
	HRESULT hr = m_diput->QueryInterface(riid, ppvObj);
	*ppvObj = this;
	return hr;
}
STDMETHODIMP_(ULONG) WrapperDirectInput8::AddRef(THIS){
	Log::log("WrapperDirectInput8::AddRef() called\n");
	return this->m_diput->AddRef();
}
STDMETHODIMP_(ULONG) WrapperDirectInput8::Release(THIS){
	Log::log("WrapperDirectInput8::Release() called() \n");
	return this->m_diput->Release();
}

WrapperDirectInput8::WrapperDirectInput8(IDirectInput8 * ptr,int _id){
	Log::log("WrapperDirectInput8::Constructor called()\n");
	this->m_diput = ptr;
	this->id=  _id;
}

/* IDirectInput8 methods*/
/*
Displays property pages for connected input devices and enables the user to map actions to device controls. The configurations must be synchronized to client.
*/
STDMETHODIMP WrapperDirectInput8::ConfigureDevices(THIS_ LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMS lpdiCDParams, DWORD dwFlags, LPVOID pvRefData){
	Log::log("WrapperDirectInput8::ConfigureDevices called, the data will sychronized to client\n");
	return this->m_diput->ConfigureDevices(lpdiCallback,lpdiCDParams,dwFlags,pvRefData);
}
/*
Creates and initializes an instance of a device based on a given globally unique identifier (GUID), and obtains an IDirectInputDevice8 Interface interface.  Build the same device remotely.
*/
STDMETHODIMP WrapperDirectInput8::CreateDevice(THIS_ REFGUID rguid,LPDIRECTINPUTDEVICE8A * lplpDirectInputDevice,LPUNKNOWN pUnkOuter){
	Log::log("wrapperDirectInput8::CreateDevice() called\n");
	Log::log("Create Input Device parameters: rguid %d, DirectInputDevice %d, UNKNOWN %d\n",rguid,lplpDirectInputDevice,pUnkOuter);

	IDirectInputDevice8 * base_device = NULL;
	//HRESULT hr = m_diput->CreateDevice(rguid,lplpDirectInputDevice,pUnkOuter);
	HRESULT hr = m_diput->CreateDevice(rguid,&base_device,pUnkOuter);
	// check the returned value
	switch(hr){
	case DIERR_DEVICENOTREG:
		Log::log("WrapperDirectInput8::crateDevice failed with DIERR_DEVICENOTREG\n");
		break;
	case DIERR_INVALIDPARAM:
		Log::log("WrapperDirectInput8::crateDevice failed with DIERR_INVALIDPARAM\n");
		break;
	case DIERR_NOINTERFACE:
		Log::log("WrapperDirectInput8::crateDevice failed with DIERR_NOINTERFACE\n");
		break;
	case DIERR_NOTINITIALIZED:
		Log::log("WrapperDirectInput8::crateDevice failed with DIERR_NOTINITIALIZED\n");
		break;
	case DIERR_OUTOFMEMORY:
		Log::log("WrapperDirectInput8::crateDevice failed with DIERR_OUTOFMEMORY\n");
		break;
	case  DI_OK:
		Log::log("WrapperDirectInput8::crateDevice succeed\n");
		break;
	default:
		Log::log("WrapperDirectInput8::crateDevice unknown return value\n");
		break;
	}
	Log::log("Create Input Device End.\n");
	// send the data to client, and build a same device

	// convert to wrapper
	WrapperDirectInputDevice8::ins_count++;
	WrapperDirectInputDevice8 *ptr = new WrapperDirectInputDevice8(base_device,WrapperDirectInputDevice8::ins_count - 1);
	if(rguid == GUID_SysMouse)
		ptr->tag = 'M';
	else if(rguid == GUID_SysKeyboard)
		ptr->tag = 'K';
	else
		ptr->tag = 0;
	*lplpDirectInputDevice = static_cast<IDirectInputDevice8 *>(ptr);
	// add the object pointer to the list
	
	return hr;
}
/*
Enumerates available devices. The function temprorally not work
*/
STDMETHODIMP WrapperDirectInput8::EnumDevices(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACK lpCallback, LPVOID pvRef, DWORD dwFlags){
	HRESULT hr = m_diput->EnumDevices(dwDevType,lpCallback,pvRef,dwFlags);
	Log::log("EnumDevices called. The program will probably use Joystick, for now, the funcion will probably failed!\n");
	return hr;
}
/*
Enumerates devices that most closely match the application-specified action map, not work for now
*/

STDMETHODIMP WrapperDirectInput8::EnumDevicesBySemantics(THIS_ LPCTSTR ptszUserName, LPDIACTIONFORMAT lpdiActionFormat,  LPDIENUMDEVICESBYSEMANTICSCB lpCallback, LPVOID pvRef, DWORD dwFlags){
	Log::log("WrapperDirectInput8::EnumDevicesBySemantics() called\n");
	HRESULT hr = m_diput->EnumDevicesBySemantics(ptszUserName,lpdiActionFormat,lpCallback,pvRef,dwFlags);
	return hr;
}
/*
Retrieves the instance globally unique identifier (GUID) of a device that has been newly attached to the system. It is called in response to a Microsoft Win32 device management notification. 


*/
STDMETHODIMP WrapperDirectInput8::FindDevice(THIS_ REFGUID rguidClass, LPCTSTR ptszName, LPGUID pguidInstance){
	Log::log("WrapperDirectInput8::FindDevice() called\n");
	HRESULT hr = m_diput->FindDevice(rguidClass,ptszName,pguidInstance);
	return hr;
}
/*
Retrieves the status of a specified device.
*/
STDMETHODIMP WrapperDirectInput8::GetDeviceStatus(THIS_ REFGUID rguidInstance){
	Log::log("WrapperDirectInput8::GetDeviceStatus() called\n");
	HRESULT hr = m_diput->GetDeviceStatus(rguidInstance);
	return hr;
}
/*
Initializes a DirectInput object. Applications normally do not need to call this method. The DirectInput8Create function automatically initializes the DirectInput object after creating it.  not work for now
*/
STDMETHODIMP WrapperDirectInput8::Initialize(THIS_ HINSTANCE hinst, DWORD dwVersion){
	Log::log("WrapperDirectInput8::Initialize() called!\n");
	HRESULT hr = m_diput->Initialize(hinst,dwVersion);
	return hr;
}
/*
 runs control panel to enable the user to install a new input device or modify configuration, the configurations must  be synchronized.
*/
STDMETHODIMP WrapperDirectInput8::RunControlPanel(THIS_ HWND hwndOwner, DWORD dwFlags){
	Log::log("WrapperDirectInput8::RunControlPanel() called!\n");
	HRESULT hr = m_diput->RunControlPanel(hwndOwner,dwFlags);
	// send the configuration data
	
	return hr;
}